package top.jle.wx.proxy.facade.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
import top.jle.jpa.basic.util.EncryptUtils;
import top.jle.wx.proxy.domain.redpack.*;
import top.jle.wx.proxy.facade.RedPacketFacade;
import top.jle.wx.proxy.feign.redPacket.RedPacketAPIFeign;

import com.google.common.base.Joiner;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import top.jle.wx.proxy.util.RandomStringUtil;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import java.util.TreeMap;

@Component
public class RedPacketFacadeImpl implements RedPacketFacade {
    private static final Logger LOGGER = LoggerFactory.getLogger(RedPacketFacadeImpl.class);
    @Autowired
    private RedPacketAPIFeign redPacketAPIFeign;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Value("${ssl.key-store.root}")
    private Resource keyStoreRoot;

    @Override
    public JSONObject sendRedPacket(SendRedPackDTO dto) throws Exception {
        dto.setNonce_str(buildNonceStr());
        dto.setSign(buildSign(dto,dto.getMch_id()));
        return redPacketAPIFeign.sendRedPack(dto);
    }
    @Override
    public JSONObject getRedPacketInfo(GetRedPackInfoDTO dto) throws Exception {
        dto.setNonce_str(buildNonceStr());
        dto.setSign(buildSign(dto,dto.getMch_id()));
        return redPacketAPIFeign.getRedPackInfo(dto);
    }
    @Override
    public JSONObject sendTransfer(TransferDTO dto) throws Exception {
        dto.setNonce_str(buildNonceStr());
        dto.setSign(buildSign(dto,dto.getMchid()));
        return redPacketAPIFeign.sendTransfer(dto);
    }
    @Override
    public JSONObject getTransferInfo(GetTransferInfoDTO dto) throws Exception {
        dto.setNonce_str(buildNonceStr());
        dto.setSign(buildSign(dto,dto.getMch_id()));
        return redPacketAPIFeign.getTransferInfo(dto);
    }

    private String buildSign(NeedSignedDTO dto, String mchId){
        SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
        filter.getExcludes().addAll(Set.of("sign","version"));
        TreeMap<String,String> map = JSONObject.parseObject(JSON.toJSONString(dto, filter), new TypeReference<>() {
        });
        return EncryptUtils.encodeMD5(Joiner.on("&").useForNull("").withKeyValueSeparator("=").join(map) + "&key=" + getSignKey(mchId)).toUpperCase();
    }
    private String buildNonceStr(){
        return RandomStringUtil.randomLettersAndDigits(12);
    }

    private String getSignKey(String mchId){
        String cacheKey = "sign-key:"+mchId;
        if(Boolean.TRUE.equals(stringRedisTemplate.hasKey(cacheKey))){
            return  stringRedisTemplate.opsForValue().get(cacheKey);
        }
        try {
            Path keyFilePath = Paths.get(keyStoreRoot.getFile().getPath() + File.separator + mchId + File.separator + "key.txt");
            String key = new String(Files.readAllBytes(keyFilePath));
            stringRedisTemplate.opsForValue().set(cacheKey,key);
            return key;
        } catch (IOException e) {
            LOGGER.error(e.getMessage(),e);

        }
        return "";
    }

}
